package com.feng.gulimall.product.service.impl;

import com.feng.gulimall.product.entity.CategoryBrandRelationEntity;
import com.feng.gulimall.product.service.CategoryBrandRelationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.feng.common.utils.PageUtils;
import com.feng.common.utils.Query;

import com.feng.gulimall.product.dao.CategoryDao;
import com.feng.gulimall.product.entity.CategoryEntity;
import com.feng.gulimall.product.service.CategoryService;
import org.springframework.util.StringUtils;


@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {
    @Autowired
    CategoryBrandRelationService categoryBrandRelationService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CategoryEntity> page = this.page(
                new Query<CategoryEntity>().getPage(params),
                new QueryWrapper<CategoryEntity>()
        );

        return new PageUtils(page);
    }

    /*
    * 查询所有分类，组装成树型结构
    * */
    @Override
    public List<CategoryEntity> listWithTree() {
        //1.查出所有分类
        //注意: 因为该ServiceImpl继承了CategoryDao,我们可以直接拿到baseMapper进行操作
        List<CategoryEntity> entities = baseMapper.selectList(null);
        //2.组装成父子类结构
        //2.1)找到所有的一级分类[一级分类的parent_id为0]
        List<CategoryEntity> level1_Menus = entities.stream().filter(categoryEntity -> {
            return categoryEntity.getParentCid() == 0;
        }).map(menu -> { //再通过map()方法将子分类的菜单保存到上一级分类中[使用递归的方法实现...]
            menu.setChildren(getChildrens(menu,entities));
            return menu;
        }).sorted((menu1,menu2) -> {
            //注意问题: 这里如果menu的Sort不存在,会报空指针异常,需要我们进行判断,如果不存在,赋值为0
            return (menu1.getSort() == null ? 0 : menu1.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort()); //以两个排序差进行排序
        }).collect(Collectors.toList());
        return level1_Menus;
    }


    /*
    * 核心方法： 递归获取所有分类的子分类的方法实现，其中方法参数：(当前分类菜单，所有分类菜单的集合)
    * */
    private List<CategoryEntity> getChildrens(CategoryEntity root,List<CategoryEntity> all) {
        List<CategoryEntity> children = all.stream().filter(categoryEntity -> {
            return categoryEntity.getParentCid() == root.getCatId(); //如果all中分类的父分类Id刚好等于当前root.Id,则表示此时的categoryEntity即为root分类的子分类
        }).map(menu -> {
            //继续递归找子分类
            menu.setChildren(getChildrens(menu,all));
            return menu;
        }).sorted((menu1,menu2) -> {
            //分类的排序
            return (menu1.getSort() == null ? 0 : menu1.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());
        }).collect(Collectors.toList());
        return children;
    }

    /*
    * 删除
    * */
    @Override
    public void removeMenuByIds(List<Long> asList) {
        //TODO 检查删除的菜单,是否被别的地方引用[后续补充此业务]
        baseMapper.deleteBatchIds(asList);
    }

    /*
    * 获取三级分类的完整路径
    * */
    @Override
    public Long[] findCatelogPath(Long catelogId) {
        //创建一个集合对象
        List<Long> path = new ArrayList<>();
        //调用一个递归方法将三级分类路径保存到Long类型的集合中
        List<Long> paths = findParentPath(catelogId,path);
        Collections.reverse(paths);
        return paths.toArray(new Long[paths.size()]);
    }

    /*
    * 递归收集所有的父节点
    * */
    private List<Long> findParentPath(Long catelogId, List<Long> paths) {
        //首先将该catelogId添加到集合中
        paths.add(catelogId);
        //然后根据catlogId获取对应的分类对象
        CategoryEntity byId = this.getById(catelogId);
        if (byId.getParentCid() != 0) {
            //说明存在父节点
            findParentPath(byId.getParentCid(),paths);
        }
        return paths;
    }

    /*
     * 级联更新: 当更新category时,顺便更新它的冗余字段对应的关联信息表的数据
     * */
    @Override
    public void updateCascade(CategoryEntity category) {
        this.updateById(category); //先更新自身
        if (!StringUtils.isEmpty(category.getName())) {
            categoryBrandRelationService.updateCategory(category.getCatId(),category.getName());
            //TODO 更新其他关联
        }
    }


}